﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using TomanuExtensions.Utils;

namespace AmiEmuLib.AmigaMachine.AmigaCPU
{
    /// <summary>
    /// Methods to work with status register.
    /// </summary>
    internal static class SR68020
    {
        public const int BIT_TRACE1 = 15;
        public const int BIT_TRACE0 = 14;
        public const int BIT_SUPERVISOR = 13;
        public const int BIT_INTERRUPT = 12;

        public const ushort MASK_TRACE1 = 1 << BIT_TRACE1;
        public const ushort MASK_TRACE0 = 1 << BIT_TRACE0;
        public const ushort MASK_TRACE = MASK_TRACE1 | MASK_TRACE0;
        public const ushort MASK_SUPERVISOR = 1 << BIT_SUPERVISOR;
        public const ushort MASK_INTERRUPT = 1 << BIT_INTERRUPT;
        public const ushort MASK_INTERRUPTS = 7 << 8;

        /// <summary>
        /// Get trace mode.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <returns></returns>
        public static TraceMode GetTrace(ushort a_sr)
        {
            return (TraceMode)(a_sr & MASK_TRACE >> BIT_TRACE0);
        }

        /// <summary>
        /// Set trace mode.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <param name="a_bitValue"></param>
        public static void SetTrace(ref ushort a_sr, TraceMode a_mode)
        {
            a_sr |= (ushort)((uint)a_mode << BIT_TRACE0);
        }

        /// <summary>
        /// Supervisor.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <returns></returns>
        public static bool IsSupervisor(ushort a_sr)
        {
            return Bits.IsSet(a_sr, BIT_SUPERVISOR);
        }

        /// <summary>
        /// Supervisor.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <param name="a_bitValue"></param>
        public static void SetSupervisor(ref ushort a_sr, bool a_bitValue)
        {
            Bits.SetBit(ref a_sr, BIT_SUPERVISOR, a_bitValue);
        }

        /// <summary>
        /// Interrupt.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <returns></returns>
        public static bool IsInterrupt(ushort a_sr)
        {
            return Bits.IsSet(a_sr, BIT_INTERRUPT);
        }

        /// <summary>
        /// Interrupt.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <param name="a_bitValue"></param>
        public static void SetInterrupt(ref ushort a_sr, bool a_bitValue)
        {
            Bits.SetBit(ref a_sr, BIT_INTERRUPT, a_bitValue);
        }

        /// <summary>
        /// Interrupt mask.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <returns></returns>
        public static uint GetInterruptMask(ushort a_sr)
        {
            return (uint)(a_sr & MASK_INTERRUPTS) >> 8;
        }

        /// <summary>
        /// Interript mask.
        /// </summary>
        /// <param name="a_sr"></param>
        /// <param name="a_mask"></param>
        public static void SetInterruptMask(ref ushort a_sr, byte a_mask)
        {
            Debug.Assert(a_mask >= 0);
            Debug.Assert(a_mask <= 7);

            a_sr = (ushort)((a_sr & ~MASK_INTERRUPTS) | (a_mask << 8));
        }

        public static string Info(ushort a_sr)
        {
            return String.Format("{0}, TRACE:{1}, SUPERVISOR:{2}, INT:{3}, INTMASK:{4}",
                Hex.UShortToHex(a_sr), GetTrace(a_sr), IsSupervisor(a_sr) ? "T" : "F",
                IsInterrupt(a_sr) ? "T" : "F", GetInterruptMask(a_sr));
        }
    }
}
